﻿using System.Collections.ObjectModel;
using nRoute.Components;
using nRoute.Samples.FutureDesktop.Model;
using nRoute.ViewModels;
using nRoute.Navigation;
using System;
using System.Windows.Threading;
using nRoute.Mapping;

namespace nRoute.Samples.FutureDesktop.ViewModels
{
    [MapViewModel(typeof(Workspaces))]
    public class WorkspacesViewModel
        : ViewModelBase
    {
        private Workspace _activeWorkspace;
        private ProxyNavigationHandler _emptyBladeHandler;

        public WorkspacesViewModel()
        {
            SetupWorkspaces();
            SetupCommands();
        }
        
#region Properties

        public ObservableCollection<Workspace> Workspaces { get; set;  }

        public Workspace ActiveWorkspace
        {
            get { return _activeWorkspace; }
            set
            {
                if (_activeWorkspace != value)
                {
                    _activeWorkspace = value;
                    NotifyPropertyChanged(() => ActiveWorkspace);
                }
            }
        }

        public ActionCommand AddNewWorkspaceCommand { get; private set; }

        public ActionCommand CloseActiveWorkspaceCommand { get; private set; }

        public ActionCommand<Workspace> SetActiveWorkspaceCommand { get; private set; }

        public ActionCommand<int> SetActiveWorkspaceIndexCommand { get; private set; }

#endregion

#region Helpers

        private void SetupWorkspaces()
        {
            Workspaces = new ObservableCollection<Workspace>
                             {
                                 new Workspace() { IsActive = true, IsSticky = true }, 
                                 new Workspace() { IsSticky = true }, 
                                 new Workspace()
                             };
            ActiveWorkspace = Workspaces[0];

            // create new handler - note this needs to be rooted as navigation handlers are weakly-referenced
            _emptyBladeHandler = new ProxyNavigationHandler();
            _emptyBladeHandler.NavigationRequested += (s, e) => AddNewWorkspace();
            NavigationService.RegisterNavigationHandler("EmptyBladeHandler", _emptyBladeHandler);
        }

        private void SetupCommands()
        {
            AddNewWorkspaceCommand = new ActionCommand(AddNewWorkspace, () => this.Workspaces.Count < 9)
            .RequeryWhenExecuted()
            .RequeryOnCollectionChanged(this.Workspaces);

            CloseActiveWorkspaceCommand = new ActionCommand(CloseActiveWorkspace, 
                () => this.Workspaces.Count > 1 && !this.ActiveWorkspace.IsSticky)
            .RequeryWhenExecuted()
            .RequeryOnPropertyChanged(this, () => ActiveWorkspace)
            .RequeryOnCollectionChanged(this.Workspaces);

            SetActiveWorkspaceCommand = new ActionCommand<Workspace>(SetActiveWorkspace);

            SetActiveWorkspaceIndexCommand = new ActionCommand<int>((i) =>
            {
                if (i < 0 || i >= this.Workspaces.Count) return;
                SetActiveWorkspace(this.Workspaces[i]);
            });
        }

        private void AddNewWorkspace()
        {
            if (this.Workspaces.Count >= 9) return;
            
            var _workspace = new Workspace();
            this.Workspaces.Add(_workspace);
            SetActiveWorkspace(_workspace);
        }

        private void CloseActiveWorkspace()
        {
            if (this.Workspaces.Count <= 1) return;

            var _currentActiveWorkspace = this.ActiveWorkspace;
            var _workspaceIndex = this.Workspaces.IndexOf(_currentActiveWorkspace);
            _workspaceIndex = (_workspaceIndex == 0) ? 1 : _workspaceIndex - 1;

            SetActiveWorkspace(Workspaces[_workspaceIndex]);
            Workspaces.Remove(_currentActiveWorkspace);
        }

        private void SetActiveWorkspace(Workspace workspace)
        {
            if (workspace == null || object.ReferenceEquals(workspace, ActiveWorkspace)) return;
            ActiveWorkspace.IsActive = false;
            workspace.IsActive = true;
            ActiveWorkspace = workspace;
        }

#endregion

    }
}